﻿using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;

// Author: Miroslav Matula m.matula@alutam.cz 
// Date : 31/8/2010

namespace System.Windows.Controls
{
	public class DataGridToolBar : DataGridToolBarBase
	{
		public DataGridToolBar()
		{
			ButtonRefreshVisible = false;

		}

    public override bool IsLoading { get { return false; } }

    public override bool IsSubmitting { get { return false; } }


		override public void ApplyFiltr()
		{
			var items = this.DataGrid.ItemsSource as ICollectionView;
			if(items==null) return;

			bool firstItem = true;
			FilterMessage.Inlines.Clear();
			foreach(var item in Filter) {
				if(!firstItem) FilterMessage.Inlines.Add(new Documents.Run() { Text = " " + LangResources.LocalizedStrings.DGTB_and + " " }); 
				FilterMessage.Inlines.Add(new Documents.Run() { Text = item.Title });
				FilterMessage.Inlines.Add(new Documents.Run() { Text = " " + item.Mark + " ", Foreground = MessageOperatorBrush });
				FilterMessage.Inlines.Add(new Documents.Run() { Text = item.Value, FontWeight = FontWeights.Black }); 
				firstItem = false;
			}
			items.Filter = null;
			_filter = null;
			items.Filter = FilterFce;
		}

		// dynamicky vytvořený filtr,lambda expression
		private Delegate _filter = null;
		// odkaz na proprty, které budou parametrem
		private PropertyInfo[] _afilterParametrs;
		private bool FilterFce(object value_)
		{
			bool isCaseSensitive = false;
			if(_filter == null) {
				//-- Definice Parametrů = PropertyInfo ----------------
				Type tv = value_.GetType();
				_afilterParametrs = new PropertyInfo[Filter.Count];
				int cnt = -1;
				foreach(var item in Filter) {
					cnt++;
					_afilterParametrs[cnt] = tv.GetProperty(item.ColumnName);
					Filter[cnt].DataType = _afilterParametrs[cnt].PropertyType;
				}
				//-- Lambda funkce ---------------
				ParameterExpression[] aex_par = new ParameterExpression[Filter.Count];
				System.Linq.Expressions.Expression xpr = null;
				System.Linq.Expressions.Expression xpr_new;
				cnt = -1;
				foreach(var item in Filter) {
					cnt++;
					xpr_new = null;
					ParameterExpression ex_par = System.Linq.Expressions.Expression.Parameter(item.DataType, "par" + cnt.ToString());
					aex_par[cnt] = ex_par;
					//-- co hledám
					object comp_val = item.Value;
					if(item.DataType == typeof(string) && !isCaseSensitive) comp_val = ((string)comp_val).ToUpper();
					if(item.DataType != typeof(string)){
						try {
							if(item.DataType == typeof(Byte)) comp_val = Byte.Parse(item.Value);
              else if(item.DataType == typeof(sbyte)) comp_val = sbyte.Parse(item.Value);
              else if(item.DataType == typeof(Int16)) comp_val = Int16.Parse(item.Value);
							else if(item.DataType == typeof(Int32)) comp_val = Int32.Parse(item.Value);
							else if(item.DataType == typeof(Int64)) comp_val = Int64.Parse(item.Value);
							else if(item.DataType == typeof(UInt16)) comp_val = UInt16.Parse(item.Value);
							else if(item.DataType == typeof(UInt32)) comp_val = UInt32.Parse(item.Value);
							else if(item.DataType == typeof(UInt64)) comp_val = UInt64.Parse(item.Value);
							else if(item.DataType == typeof(decimal)) comp_val = decimal.Parse(item.Value);
							else if(item.DataType == typeof(Double)) comp_val = Double.Parse(item.Value);
							else if(item.DataType == typeof(Single)) comp_val = Single.Parse(item.Value);
							else if(item.DataType == typeof(DateTime)) comp_val = DateTime.Parse(item.Value);
						} catch { 
							//-- špatně zadaná podmínka
							//-- zapis do message
							//-- true filter
							FilterMessage.Inlines.Clear();
							FilterMessage.Inlines.Add(new Documents.Run() { Text = "Wrong value: " + item.Value, Foreground = new Media.SolidColorBrush(Media.Colors.Red)});
							var items = this.DataGrid.ItemsSource as ICollectionView;
							items.Filter = null;
							return false;
						} 
					}

					ConstantExpression ex_const = System.Linq.Expressions.Expression.Constant(comp_val);
					//-- Volba kritéria ------------------------------------------
					switch(item.Operator) {
						case FilterOperator_DGTB.Contains:
						xpr_new = System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("Contains", new[] { typeof(string) }), ex_const);
						break;
						case FilterOperator_DGTB.EndsWith:
						xpr_new = System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("EndsWith", new[] { typeof(string) }), ex_const);
						break;
						case FilterOperator_DGTB.StartsWith:
						xpr_new = System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("StartsWith", new[] { typeof(string) }), ex_const);
						break;
						//case FilterOperator.IsContainedIn:
						//	xpr_new = System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("", new[] { typeof(string) }), ex_const);
						//break;
						case FilterOperator_DGTB.IsEqualTo:
						xpr_new = System.Linq.Expressions.Expression.Equal(ex_par, ex_const);
						break;
						case FilterOperator_DGTB.IsGreaterThan:
						if(item.DataType == typeof(string)) {
							xpr_new = System.Linq.Expressions.Expression.GreaterThan(
								System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("CompareTo", new[] { typeof(string) }), ex_const)
								, System.Linq.Expressions.Expression.Constant(0));
						} else {
							xpr_new = System.Linq.Expressions.Expression.GreaterThan(ex_par, ex_const);
						}
						break;
						case FilterOperator_DGTB.IsGreaterThanOrEqualTo:
						if(item.DataType == typeof(string)) {
							xpr_new = System.Linq.Expressions.Expression.GreaterThanOrEqual(
								System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("CompareTo", new[] { typeof(string) }), ex_const)
								, System.Linq.Expressions.Expression.Constant(0));
						} else {
							xpr_new = System.Linq.Expressions.Expression.GreaterThanOrEqual(ex_par, ex_const);
						}
						break;
						case FilterOperator_DGTB.IsLessThan:
						if(item.DataType == typeof(string)) {
							ex_const = System.Linq.Expressions.Expression.Constant(comp_val + "ZZZZZZZZZZZZZZ");
							xpr_new = System.Linq.Expressions.Expression.LessThan(
								System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("CompareTo", new[] { typeof(string) }), ex_const)
								, System.Linq.Expressions.Expression.Constant(0));
						} else {
							xpr_new = System.Linq.Expressions.Expression.LessThan(ex_par, ex_const);
						}
						break;
						case FilterOperator_DGTB.IsLessThanOrEqualTo:
						if(item.DataType == typeof(string)) {
							ex_const = System.Linq.Expressions.Expression.Constant(comp_val + "ZZZZZZZZZZZZZZ");
							xpr_new = System.Linq.Expressions.Expression.LessThanOrEqual(
								System.Linq.Expressions.Expression.Call(ex_par, typeof(String).GetMethod("CompareTo", new[] { typeof(string) }), ex_const)
								, System.Linq.Expressions.Expression.Constant(0));
						} else {
							xpr_new = System.Linq.Expressions.Expression.LessThanOrEqual(ex_par, ex_const);
						}
						break;
						case FilterOperator_DGTB.IsNotEqualTo:
						xpr_new = System.Linq.Expressions.Expression.NotEqual(ex_par, ex_const);
						break;
					}
					//--  -------------------------------------
					if(xpr == null) {
						xpr = xpr_new;
					} else {
						xpr = System.Linq.Expressions.BinaryExpression.AndAlso(xpr, xpr_new);
					}
				}

				if(xpr != null) {
					LambdaExpression lex = System.Linq.Expressions.Expression.Lambda(xpr, aex_par);
					_filter = lex.Compile();
				}

			}
			bool res = true;
			if(_filter != null) {
				// pole parametrů
				object[] par = new object[_afilterParametrs.Length];
				for(int i = 0; i < _afilterParametrs.Length; i++) {
					object vv = _afilterParametrs[i].GetValue(value_, null);
					if(vv == null) return false; // nelze provést vyhodnocení
					if(_afilterParametrs[i].PropertyType == typeof(string) && !isCaseSensitive) vv = ((string)vv).ToUpper();
					par[i] = vv;
				}
				res = (bool)_filter.DynamicInvoke(par);
			}
			return res;
		}

		public override bool DataHasChanges
		{
			get
			{
				return false;
			}
		}

	}
}
